---
title: Plugin Components
description: Learn how to create and style custom components for Plate plugins.
---

By default, Plate plugins are headless, meaning all nodes will be rendered as plain text. This guide will show you how to create and style custom components for your editor.

## Plate UI

Unless you prefer to build everything from scratch, we recommend using [Plate UI](/docs/components) to get started. Plate UI is a collection of components that you can copy into your app and modify to suit your needs.

The process of creating and registering components is similar whether you use Plate UI or build your own from scratch.

## Defining Components

Use `PlateElement` for element nodes (like paragraphs, headings) and `PlateLeaf` for text leaf nodes (like bold, italic). These components handle applying the necessary Plate props to your custom HTML elements.

Ensure the `children` prop is rendered unconditionally for the editor to function correctly, even for void nodes.

### Element Component

```tsx
import { type PlateElementProps, PlateElement } from 'platejs/react';

export function BlockquoteElement(props: PlateElementProps) {
  // props contains attributes, children, element, editor, etc.
  // plus any custom props your plugin might pass.
  return (
    <PlateElement
      as="blockquote"
      className="my-1 border-l-2 pl-6 italic" // Apply custom styles directly
      {...props} // Pass all original props (attributes, children, element, etc.)
    />
  );
}
```

This example defines a `BlockquoteElement`. The `as` prop on `PlateElement` specifies that it should render an HTML `<blockquote>`. `PlateElement` handles rendering the `children` passed via `{...props}`.

### Leaf Component

```tsx
import { type PlateLeafProps, PlateLeaf } from 'platejs/react';

export function CodeLeaf(props: PlateLeafProps) {
  // props contains attributes, children, leaf, text, editor, etc.
  // plus any custom props your plugin might pass.
  return (
    <PlateLeaf
      as="code"
      className="rounded-md bg-muted px-[0.3em] py-[0.2em] font-mono text-sm" // Apply custom styles
      {...props} // Pass all original props (attributes, children, leaf, text, etc.)
    />
  );
}
```

### Styling

We recommend styling components using Tailwind CSS, as demonstrated in Plate UI.

Alternatively, Plate generates class names like `slate-<node-type>` (e.g., `slate-p` for paragraphs, `slate-h1` for H1 headings) which you can target with global CSS:

```css
.slate-p {
  margin-bottom: 1rem;
}
.slate-bold {
  font-weight: bold;
}
```

## Register Components

To use your custom components, register them with the corresponding plugin or directly in the editor configuration.

### Method 1: Plugin's `withComponent` (Recommended)

The `withComponent` method is the most straightforward way to associate a component with a plugin.

```tsx
const plugins = [
  // This is equivalent to:
  // ParagraphPlugin.configure({ node: { component: MyParagraphElement }});
  ParagraphPlugin.withComponent(MyParagraphElement),
  CodeBlockPlugin.withComponent(MyCodeBlockElement),
  CodeLinePlugin.withComponent(MyCodeLineElement),
  CodeSyntaxPlugin.withComponent(MyCodeSyntaxLeaf),
]
```


### Method 2: Plugin `override.components`

For plugins that manage multiple component parts (like `CodeBlockPlugin` with `code_block`, `code_line`, and `code_syntax`), or when you need to override components for a specific plugin instance, use the `override.components` option within `configure`.

```tsx
const plugins = [
  CodeBlockPlugin.configure({
    override: {
      components: {
        [CodeBlockPlugin.key]: MyCodeBlockElement,
        [CodeLinePlugin.key]: MyCodeLineElement,
        [CodeSyntaxPlugin.key]: MyCodeSyntaxLeaf,
      },
    },
  }),
];
```

### Method 3: Editor `components` Option

You can globally map plugin keys to components in `createPlateEditor` (or `usePlateEditor`). This is useful for managing all components in one place, or for plugins composed of multiple plugins.

```tsx
const editor = createPlateEditor({
  plugins: [ParagraphPlugin, CodeBlockPlugin /* ...other plugins */],
  components: {
    [ParagraphPlugin.key]: MyParagraphElement,
    [CodeBlockPlugin.key]: MyCodeBlockElement,
    [CodeLinePlugin.key]: MyCodeLineElement,
    [CodeSyntaxPlugin.key]: MyCodeSyntaxLeaf,
    // ...other component overrides
  },
});
```
